package com.mcdao.wssdemo.server;

import java.util.LinkedHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.HandshakeComplete;
import io.netty.util.AttributeKey;
import io.netty.util.CharsetUtil;

public class WssServerHandler extends SimpleChannelInboundHandler<Object> {

	public static final Logger logger = LogManager.getLogger(WssServerHandler.class);

	private LinkedHashMap<Long, Channel> connectionMap = new LinkedHashMap<Long, Channel>();
	private AttributeKey<Long> connSeq = AttributeKey.valueOf("Conn");
	public static long connectionSeq = 0L;

	public static synchronized long nextSeq() {
		return ++connectionSeq;
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) {
		logger.debug("WebSocket Client disconnected!");
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
		Channel ch = ctx.channel();
		if (msg instanceof FullHttpResponse) {
			FullHttpResponse response = (FullHttpResponse) msg;
			throw new IllegalStateException("Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
		}
		WebSocketFrame frame = (WebSocketFrame) msg;

		if (frame instanceof TextWebSocketFrame) {
			String request = ((TextWebSocketFrame) frame).text();
			ctx.channel().writeAndFlush(new TextWebSocketFrame(request));
		}
		if (frame instanceof PongWebSocketFrame) {
			logger.debug("WebSocket Client received pong");
		} else if (frame instanceof CloseWebSocketFrame) {
			logger.debug("WebSocket Client received closing");
			ch.close();
		}

	}

	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		logger.info("Online [address: {}]", ctx.channel().remoteAddress());
		super.channelRegistered(ctx);
	}

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt instanceof HandshakeComplete) {
			handshakeHandler(ctx, (HandshakeComplete) evt);
		}
		super.userEventTriggered(ctx, evt);
	}

	public void handshakeHandler(ChannelHandlerContext ctx, HandshakeComplete evt) {
		ctx.channel().attr(connSeq).set(nextSeq());
		connectionMap.put(connectionSeq, ctx.channel());
		ctx.channel().writeAndFlush(new TextWebSocketFrame("ping"));
		logger.info("[握手] [成功] [Address:{}] [Conn:{}]", new Object[] { ctx.channel().remoteAddress(), connectionSeq });
	}
}
